'use strict';

import clone from './shallow-clone';
import typeOf from './kind-of';
import isPlainObject from './is-plain-object';

/**
 * 深度克隆任意值。
 * @param {*} val 要克隆的值。
 * @param {Function} [instanceClone] 可选的自定义克隆函数。
 * @returns {*} 克隆后的值。
 */
function cloneDeep(val, instanceClone) {
  const type = typeOf(val);
  if (type === 'object') {
    return cloneObjectDeep(val, instanceClone);
  }
  if (type === 'array') {
    return cloneArrayDeep(val, instanceClone);
  }
  return clone(val);
}

/**
 * 深度克隆对象。
 * @param {Object} val 待克隆的对象。
 * @param {Function} [instanceClone] 可选的自定义克隆函数。
 * @returns {Object} 克隆后的对象。
 */
function cloneObjectDeep(val, instanceClone) {
  if (typeof instanceClone === 'function') {
    return instanceClone(val);
  }
  if (instanceClone || isPlainObject(val)) {
    const res = (val.constructor !== undefined) ? new val.constructor() : Object.create(null);
    // 使用 Object.keys 遍历对象自身属性
    Object.keys(val).forEach(key => {
      res[key] = cloneDeep(val[key], instanceClone);
    });
    return res;
  }
  return val;
}

/**
 * 深度克隆数组。
 * @param {Array} val 待克隆的数组。
 * @param {Function} [instanceClone] 可选的自定义克隆函数。
 * @returns {Array} 克隆后的数组。
 */
function cloneArrayDeep(val, instanceClone) {
  // 使用 map() 简化数组克隆逻辑，保持数组构造信息由 map() 内部处理
  return val.map(item => cloneDeep(item, instanceClone));
}

export default cloneDeep;